<template>
    <tnxel-submit-form :model="model">
        <el-form-item label="同时生成下列枚举类型映射器：" label-position="top" v-if="converterItems.length">
            <tnxel-select v-model="model.autoConverters"
                :items="converterItems"
                selector="checkbox"
            />
        </el-form-item>
        <el-form-item label="文件" label-width="44px">{{ model.path }}</el-form-item>
        <tnxel-alert type="error" class="mb-0" v-if="model.error"> {{ model.error }}</tnxel-alert>
        <template v-else-if="model.code">
            <CodePreview language="xml" :code="model.code"/>
            <div class="flex-v-center justify-content-end mt-3">
                <tnxel-button icon="fa-solid fa-floppy-disk" @click="save">
                    保存JPA映射代码到文件
                </tnxel-button>
                <tnxel-button icon="fa-solid fa-copy" @click="copy">
                    复制JPA映射代码到剪切板
                </tnxel-button>
            </div>
        </template>
    </tnxel-submit-form>
</template>

<script>
import tnx from '@/tnx';
import ModelingApp from '@/logic/modeling/entity/ModelingApp.js';
import EntityClass from '@/logic/modeling/entity/EntityClass.js';
import PersistUtil from '@/logic/modeling/util/persist.js';
import GenerateUtil from '@/logic/modeling/util/generate.js';
import CodingType from '@/logic/coding/model/CodingType.js';

import CodePreview from './components/CodePreview.vue';

export default {
    components: {
        CodePreview,
    },
    props: {
        app: {
            type: ModelingApp,
            required: true,
        },
        clazz: {
            type: EntityClass,
            required: true,
        },
    },
    data() {
        return {
            mavenProject: null,
            model: {
                path: null,
                autoConverters: [],
                code: null,
                error: null,
            },
            converters: {},
        };
    },
    computed: {
        superClassWithInheritanceStrategy() {
            return this.app.getSuperClassWithInheritanceStrategy(this.clazz);
        },
        converterItems() {
            let items = [];
            for (let className in this.converters) {
                items.push({
                    value: className,
                    text: className,
                });
            }
            return items;
        },
    },
    mounted() {
        PersistUtil.loadRelativeMavenProject(this.app.path).then(mavenProject => {
            this.mavenProject = mavenProject;
            this.refresh();
        });
    },
    methods: {
        refresh() {
            if (!this.model.path) {
                let root = tnx.util.file.getParentDir(this.app.path);
                this.model.path = GenerateUtil.getPath(root, this.mavenProject, this.clazz, 'jpa');
            }
            if (!this.model.code) {
                let result = GenerateUtil.generateJpaMappingXmlCode(this.app, this.clazz,
                    this.superClassWithInheritanceStrategy);
                this.model.code = result.code;
                this.converters = result.converters;
                this.model.autoConverters = Object.keys(result.converters);
                for (let converterClassName in this.converters) {
                    this.generateConverter(converterClassName);
                }
            }
        },
        generateConverter(converterClassName) {
            let converter = this.converters[converterClassName];
            if (converter) {
                if (!converter.path) {
                    let root = tnx.util.file.getParentDir(this.app.path);
                    let converterClass = new CodingType(converterClassName);
                    converter.path = GenerateUtil.getPath(root, this.mavenProject, converterClass, 'converter');
                }
                if (!converter.code) {
                    converter.code = GenerateUtil.generateEnumConverterCode(converter.enumClass, converter.arrayed);
                }
            }
            return converter;
        },
        save() {
            this.saveConverters(() => {
                GenerateUtil.save(this.model.path, this.model.code, 'jpa');
            });
        },
        saveConverters(callback) {
            let total = 0;
            for (let converterClassName of this.model.autoConverters) {
                let converter = this.converters[converterClassName];
                if (converter) {
                    tnx.util.file.exists(converter.path).then(exists => {
                        // 转换器类的代码没有改动空间，不存在时才执行保存
                        if (exists) {
                            if (++total === this.model.autoConverters.length) {
                                callback();
                            }
                        } else {
                            tnx.util.file.write(converter.path, converter.code).then(() => {
                                if (++total === this.model.autoConverters.length) {
                                    callback();
                                }
                            });
                        }
                    });
                } else {
                    if (++total === this.model.autoConverters.length) {
                        callback();
                    }
                }
            }
        },
        copy() {
            GenerateUtil.copy(this.model.code);
        },
    }
}
</script>

<style lang="scss" scoped>
</style>
